从一道笔试题开始
1 | async function async1() { |
执行栈与任务队列
- JS分为同步任务和异步任务。
- 同步任务都在主线程上执行,形成一个执行栈。
- 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。
- 一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。
执行栈
可以把执行栈认为是一个存储函数调用的栈结构,遵循先进后出的原则。
当我们调用一个方法的时候,JavaScript 会生成一个与这个方法对应的执行环境,又叫执行上下文(context)。
由于 JavaScript 是单线程的,这些方法就会按顺序被排列在一个单独的地方,这个地方就是所谓执行栈。
任务队列
事件队列是一个存储着 异步任务 的队列,其中的任务严格按照时间先后顺序执行。
宏任务与微任务
- 异步任务分为 宏任务(macrotask) 与 微任务 (microtask)。
- 宏任务会进入一个队列,而微任务会进入到另一个不同的队列,且微任务要优于宏任务执行。
- 一个宏任务在执行的过程中添加一些微任务,在当前的微任务没有执行完成时,不会执行下一个宏任务的
宏任务
宏任务包括 script , setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering
微任务
微任务包括 process.nextTick ,promise ,MutationObserver,其中 process.nextTick 为 Node 独有。
笔试题思路
await
从字面意思上看await就是等待,await 等待的是一个表达式,这个表达式的返回值可以是一个promise对象也可以是其他值。
await是一个让出线程的标志。await之前的代码同步执行,由于async await本身就是promise+generator的语法糖,所以await后面的代码是microtask。
1 | async function async1() { |
两道练习题
第一题
1 | const p1 = new Promise((resolve, reject) => { |
第二题
1 | const p1 = new Promise((resolve, reject) => { |
注意两道题区别,p1 then() 里面,第一题是 new 一个 Promsie,第二题是 return 一个 Promise。new 的 Promise then回调会进入任务队列,而 return 的 Promise 其结果会被 resolve,所以第 18 行的 then 回调只有等这个Promise全部执行完再执行。